iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
1
AI & Data

D3.js資料視覺化的浪漫突進系列 第 17

Day17 D3js d3.brush與d3.zoom實現選取放大功能

  • 分享至 

  • xImage
  •  

title: d3-it30-day17
tags: d3-it30

D3js d3.brush與d3.zoom實現選取放大功能

用途

d3.brush可以產生選區區塊,接著就可以透過d3.zoom進行對應的縮放!

brushed事件

範例

const brush = d3.brush().on("end", function(event){});
  • start - 當開始筆刷選取的時候,類似mousedown。
  • brush - 當移動筆刷選取區的時候,類似mousemove。
  • end - 當停止筆刷選取的時候,類似mouseup。

有以上這三種事件可以讓我們監聽。而得到的事件中有包含幾個部分。

範例

const brush = d3.brush().on("end", function(event){
    console.log(event);
});

  • target - 筆刷相關的行為。
  • type - 筆刷事件類別,就是上方start, brush, end三種。
  • selection - 目前筆刷選取的範圍。
  • sourceEvent - 原始事件。目前沒有特別用途,但此事件的細節都會在這。
  • mode - 筆刷的模式,有drag, space, handle, center這幾種。

實際範例

範例:

...以上省略
const brush = d3.brush().on("end", brushed);

const brushLayer = rootLayer.append("g")
                .attr("class", "brush")
                .call(brush);

function brushed(event) {
  if (!event.selection) { // 以防根本沒選東西,造成取selection的error
    xScale = d3.scaleTime().range([0, innerWidth]).domain(xExtent);
    yScale = d3.scaleLinear().range([innerHeight, 0]).domain(yExtent);
    // 如果沒選東西,xScale, yScale就恢復原狀(未放大的狀態)
  } else {
    // 如果有選擇區塊,selection會產出一個二維陣列,分別代表`x0`, `x1`, `y0`, `y1`,左上到右下的位置,讓你有辦法重新計算目前位置的extent,進而達到放大的效果。
    const x0 = event.selection[0][0];
    const y0 = event.selection[0][1];
    const x1 = event.selection[1][0];
    const y1 = event.selection[1][1];
    // 因目前得到的只是選區位置,需要對應出相較資料源的值,才能重新計算`scale`
    xScale.domain([x0, x1].map(xScale.invert));
    yScale.domain([y0 , y1].map(yScale.invert)); 
  }  
  
  // 此步驟zoom會重新計算對應位置
  zoom();
}

function zoom() {
  //...重新計算對應位置的function
}

整個流程

1. 選取範圍

2. 事件接收到筆刷選取事件

3. 得到目前選取的範圍(這輛的範圍是圖上座標,不是對應資料的數值)

4. 使用`scale.invert`算出圖上座標對應資料源的數值得到目前範圍的資料數值。

5. 重新計算`scale`

6. 重新繪製所有需要scale的元件

7. done!
 

結論

非常方便的事件,可以幫我們處理複雜的選取問題,而只要專注在重新繪製上就好,非常容易使用。

範例Codepen

參考

d3-brush


上一篇
Day16 d3-brush輔助工具
下一篇
Day18 D3js d3.path麻煩的線段路徑
系列文
D3.js資料視覺化的浪漫突進30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言